﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
using SNM = System.Net.Mail;
using CodeCamp.Infrastructure;
using CodeCamp.Models.Home;
using CodeCamp.Models.Shared;
using RGoodSW.Logger.Interfaces;
using CCM = CodeCamp.Model;

namespace CodeCamp.Controllers
{
  [HandleError]
  public class HomeController : ControllerBase
  {
    private static class Tags
    {
      internal const string contactToEmailAddress = "contactToEmailAddress";
    }

    public HomeController(IDefaultValueProvider defaultValueProvider, ILoggerExtended logger)
      : base(defaultValueProvider, logger)
    {
    }

    public ActionResult Index( string eventName )
    {
      using (var repository = new CodeCampDataRepository())
      {
          var ccEvent = EventsHelper.GetEvent(repository, eventName, DefaultEventShortName, this.User);
          SetSharedViewBagProperties(ccEvent);
          var eventSponsors = repository.GetSponsors(ccEvent.Id);

          // assemble model
          var sponsors = new List<HomeIndexViewModel.Sponsor>();
          foreach (var sponsor in eventSponsors)
          {
              var scaledImage =
                SponsorsHelper.GetScaledImageSize(sponsor.ImageWidth, sponsor.ImageHeight);
              sponsors.Add(
                new HomeIndexViewModel.Sponsor
                {
                    Name = sponsor.Name,
                    Url = sponsor.Url,
                    ImageUrl = sponsor.ImageUrl,
                    ImageWidth = scaledImage.Width,
                    ImageHeight = scaledImage.Height
                });
          }
          sponsors.PermuteRandomly();

          HomeIndexViewModel model = 
            new HomeIndexViewModel
            {
                //DefaultEventShortName = this.DefaultEventShortName,
                //EventDisplayName = eventDisplayName,
                //EventShortName = eventName,
                DisplayDate = (ccEvent.DisplayDate ?? ""),
                DisplayLocation = (ccEvent.DisplayLocation ?? ""),
                Sponsors = sponsors
            };

          SetSharedEventProperties(ccEvent, model, repository);

          return View(model);
      }
    }

    public ActionResult About( string eventName )
    {
      using (var repository = new CodeCampDataRepository())
      {
          var ccEvent = EventsHelper.GetEvent(repository, eventName, DefaultEventShortName, this.User);
          SetSharedViewBagProperties(ccEvent);
          HomeAboutViewModel model = new HomeAboutViewModel();
          SetSharedEventProperties(ccEvent, model, repository);
          var events = repository.GetEventsInDisplayOrder()
                          .Where(e => e.ShortName != model.EventShortName)
                          .Where(e => e.EventStartDate < ccEvent.EventStartDate)
                          .ToList();
          FillOtherCCEvents(events, model.OtherCCEvents);

          return View(model);
      }
    }

    public ActionResult Directions(string eventName)
    {
        using (var repository = new CodeCampDataRepository())
        {
            var ccEvent = EventsHelper.GetEvent(repository, eventName, DefaultEventShortName, this.User);
            SetSharedViewBagProperties(ccEvent);
            CommonViewModel model = new CommonViewModel
            {
                DisplayDate = (ccEvent.DisplayDate ?? ""),
                DisplayLocation = (ccEvent.DisplayLocation ?? "")
            };
            SetSharedEventProperties(ccEvent, model, repository);
            //*** Put XXXXDirectionsPartial.cshtml (where XXXX is event ShortName)
            //*** in the Shared\Partial folder so it will allow the shared view model to be correctly updated
            string partialName = string.Format("Partial/{0}Directions", ccEvent.ShortName);
            ViewEngineResult partial = ViewEngines.Engines.FindView(this.ControllerContext, partialName, null);
            if ((partial != null) && (partial.View != null))
                model.PartialView = partialName;
            else
                RedirectToAction("Index");

            return View(model);
        }
    }

    private string ContactToEmailAddress
    {
        get
        {
            string contactToEmailAddress = DefaultValueProvider.GetStringValueOrNull(Tags.contactToEmailAddress);
            return contactToEmailAddress;
        }
    }

    public ActionResult Contact(string eventName)
    {
        using (var repository = new CodeCampDataRepository())
        {
            var ccEvent = EventsHelper.GetEvent(repository, eventName, DefaultEventShortName, this.User);
            SetSharedViewBagProperties(ccEvent);
            ContactViewModel model = new ContactViewModel();
            if (string.IsNullOrWhiteSpace(ContactToEmailAddress))
            {
                model.ContactEnabled = false;
            }
            else
            {
                model.ContactEnabled = true;
                model.ContactDetail = new ContactDetailViewModel();
            }
            SetSharedEventProperties(ccEvent, model, repository);

            if ((model.ContactDetail != null) && UserIsAuthenticated(this.User) && SiteUserId.HasValue)
            {
                CCM.SiteUser siteUser = GetSiteUser(repository, this.User, UserIsAuthenticated(this.User));
                if (siteUser != null)
                {
                    model.ContactDetail.Name = string.Concat(siteUser.FirstName, " ", siteUser.LastName).Trim();
                    model.ContactDetail.EmailAddress = siteUser.EmailAddress;
                }
            }

            return View(model);
        }
    }


    [CaptchaMvc.Attributes.CaptchaVerify("Entry does not match captch image.")]
    [HttpPost]
    public ActionResult Contact(string eventName, ContactDetailViewModel model)
    {
        using (var repository = new CodeCampDataRepository())
        {
            var ccEvent = EventsHelper.GetEvent(repository, eventName, DefaultEventShortName, this.User);

            if (ModelState.IsValid)
            {
                string contactToEmailAddress = ContactToEmailAddress;
                if (string.IsNullOrWhiteSpace(contactToEmailAddress))
                {
                    ModelState.AddModelError("", "Contact not enabled.");
                }
                else
                {
                    System.Text.StringBuilder logMsg = new System.Text.StringBuilder();
                    try
                    {
                        logMsg.AppendFormat("Home/Contact POST from \"{1}\" {2} {0}UserAgent=\"{3}\" {0}Sending email... {0}",
                            Environment.NewLine,
                            model.EmailAddress,
                            this.Request.UserHostAddress,
                            this.Request.UserAgent);

                        SNM.MailAddress fromAddress = new SNM.MailAddress(model.EmailAddress);
                        SNM.MailAddress toAddress = new SNM.MailAddress(contactToEmailAddress);
                        SNM.SmtpClient mailClient = new SNM.SmtpClient();
                        System.Text.StringBuilder messageBody = new System.Text.StringBuilder();
                        messageBody.AppendFormat("{1} Contact from {2}{0}----------{0}{3}{0}",
                            Environment.NewLine,
                            ccEvent.ShortName,
                            model.Name,
                            model.Message);
                        string subject = string.Concat(ccEvent.ShortName, ": ", model.Subject);
                        bool invalidToEmailAddress;
                        if (SendEmail(mailClient, fromAddress, toAddress, subject, messageBody, "Account/ResetAcct POST",
                            out invalidToEmailAddress))
                        {
                            Logger.Info(logMsg.ToString());
                            return RedirectToAction("Index");
                        }
                        if (invalidToEmailAddress)
                        {
                            logMsg.Append("Invalid to address.");
                        }
                        else
                        {
                            logMsg.Append("Error sending email.");
                        }
                        Logger.Warn(logMsg.ToString());
                        ModelState.AddModelError("", "Error processing contact information.");
                    }
                    catch (Exception ex)
                    {
                        if (logMsg.Length == 0)
                            logMsg.Append("Contact POST");
                        LogException(logMsg.ToString(), ex);
                    }
                }
            }

            SetSharedViewBagProperties(ccEvent);
            ContactViewModel viewModel = new ContactViewModel();
            viewModel.ContactEnabled = true;
            viewModel.ContactDetail = model;
            SetSharedEventProperties(ccEvent, viewModel, repository);

            return View(viewModel);
        }
    }

    private void FillOtherCCEvents(List<CCM.Event> events, List<CCEventListItem> eventList)
    {
        foreach (var event_ in events)
        {
            CCEventListItem item = new CCEventListItem
            {
                Id = event_.Id,
                DisplayDate = event_.DisplayDate,
                DisplayName = event_.DisplayName,
                DisplaySortOrder = event_.DisplaySortOrder,
                EventIsPublic = event_.EventIsPublic,
                EventStartDate = event_.EventStartDate,
                ShortName = event_.ShortName
            };

            if (!item.EventIsPublic)
            {
                if (User.IsInRole(CCRoles.RoleNames.BigCheeze)
                    || (!string.IsNullOrWhiteSpace(event_.NonPublicEventPreviewRole) && this.User.IsInRole(event_.NonPublicEventPreviewRole)))
                {
                    eventList.Add(item);
                }
            }
            else
            {
                eventList.Add(item);
            }
        }
    }

    public ActionResult OtherCCEvents(string eventName)
    {
        using (var repository = new CodeCampDataRepository())
        {
            var ccEvent = EventsHelper.GetEvent(repository, eventName, DefaultEventShortName, this.User);
            SetSharedViewBagProperties(ccEvent);
            HomeAboutOtherCCEventsViewModel model = new HomeAboutOtherCCEventsViewModel();
            SetSharedEventProperties(ccEvent, model, repository);
            var events = repository.GetEventsInDisplayOrder()
                            .Where( e => e.ShortName != model.EventShortName )
                            .ToList();

            FillOtherCCEvents(events, model.OtherCCEvents);

            return View(model);
        }
    }
  }
}
